package demo01_basicGrammer

/**
 * 函数：把一些经常使用的代码做封装，避免代码的冗余
 * 与方法的区别
 *    方法：一定与类和对象有关
 *    函数：可以与类和对象无关
 */
object Demo05_function_basic {

  /**
   * 1.定义函数
   *    java中定义
   *      访问修饰符 返回值类型 方法名([参数类型 参数名,...]){
   *        方法体
   *      }
   *
   *    scala中定义
   *      访问修饰符：如果不写，相当于是 public
   *      返回值类型：可以不写，可以通过类型推导来确定
   *      函数名：必须要有的
   *      参数：表示参数的小括号，如果没有参数的话，可以不写
   *      大括号：在scala中，大括号是表达式块，要在两句及以上的情况下才必须使用
   *      比java多的：= 在函数名和函数体中间要加等号
   *
   * 2.scala中调用函数与java中一致
   * @return
   */

   //3.1.1 没有括号的无参:调用的时候不能加括号
   def function_noArgs={
     println("没有括号的无参函数")
   }

   //3.1.2 有括号的无参:调用的使用可以加括号也可以不加括号
   def function_noArgs_sign()={
     println("有括号的无参函数")
   }

   //3.2.1 普通的有参函数:必须按照形参的顺序依次传参，且参数的个数必须与形参保持一致
   def function_normalArgs(name:String,age:Int) = {
     println("普通的有参函数")
   }

   //3.2.2 有默认只的有参函数:如果不传默认值参数就是用默认值，如果传默认值参数，就使用实参,有默认值的参数尽量排在最后面
   def function_defaultValueArgs(name:String,age:Int,gender:String = "男") = {
     println(s"${name}:${age}:${gender}")
   }

   //3.2.3 指定形参传参的有参函数:把形参当成key，把实参当成value，对指定的key赋value值。好处是可以略过默认的参数也可以不受顺序的限制
   def function_specificValueArgs(name:String="tom",age:Int,gender:String = "男") = {
     println(s"${name}:${age}:${gender}")
   }

   //3.2.4 不定长参数:本质就是数组，可以直接遍历循环使用
   def function_noLimitLengthValueArgs(nums:Int*)={
     var sum = 0;
     for(num <- nums){
       sum+=num
     }
     println(s"sum:${sum}")
   }

   //3.2.5 参数组，把一个函数中的多个参数，分别用小括号进行表示，从结果的角度没有任何区别，但是从理解的角度可以理解为函数的链式调用
   def function(name:String)(age:Int) = {
     println(s"name:${name}:age:${age}")
   }

   //4.嵌套函数:java中不支持嵌套函数
   //  scala中可以在函数中定义函数，内部的函数相当于是外部函数的工具，但是作用于只能在外部函数内使用
   def getMaxThree(x:Int,y:Int,z:Int)={
      def getMaxTwo(a:Int,b:Int)={
        if(a>b) a else b
      }
      getMaxTwo(getMaxTwo(x,y),z)
   }

   //5.递归：代码简单，逻辑不好理解，性能不好
   def power(x:Int,n:Int):Long = {
     if (n>=1) x*power(x,n-1)
     else 1
   }

   // 尾递归：从内存的角度做了一些优化  必须保证最后一句执行的内容是调用本身的函数
   @annotation.tailrec
   def power(x:Int,n:Int,t:Int=1):Long={
     if(n<1)t
     else power(x,n-1,x*t)
   }

   def main(args: Array[String]): Unit = {
     function("tom")(111)
   }
}
